#include <fstream>
#include <vector>

#include "Session.h"
#include "Hooks.h"
#include "WinMacroLib.h"
#include "MacroFileWriter.h"

class CRecordingSession;

extern CRecordingSession *g_pRecordingSession;

class CRecordingSession : public Session
{
	std::string file_name;	
	bool ignore_mouse_actions;

	bool recording;
	RECORDINGSTOPPEDPROC recording_stopped_proc;
	RECORDINGOPTIONS recording_options;

	std::vector<EVENTMSG> recorded_messages;
	DWORD number_of_messages;

public:
	CRecordingSession(LPCTSTR fileName, HINSTANCE module_instance, RECORDINGOPTIONS options,
		RECORDINGSTOPPEDPROC proc)
		: Session(module_instance), number_of_messages(0)
	{
		this->file_name = fileName;
		this->recording_options = options;
		this->ignore_mouse_actions = ignore_mouse_actions;
		recording_stopped_proc = proc;
	}

	DWORD Start()
	{
		hook_handle = SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProc, module_instance, 0);
		InstallGetMsgHook();

		if ((hook_handle == NULL) || (getmsg_hook_handle == NULL))
		{
			DWORD error = GetLastError();
			SessionCancelled();
			return error;
		}
		else
		{
			start_time = GetTickCount();
			//Change flag variable to indicate we are now recording	
			recording = true;
			return 0;
		}
	}

	virtual void SessionStopped()
	{	
		if (recording == false)
			return;

		//Set bool variable back to original value to indicate recording is over
		recording = false;

		CMacroFileWriter writer;
		writer.WriteMacroFile(file_name.c_str(), recorded_messages);
		
		if (recording_stopped_proc)
			recording_stopped_proc();

		g_pRecordingSession = NULL;
		delete this;
	}

	void AppendToFile(EVENTMSG *pMsg)
	{
		//Subtract message tick count from the start of recording tick count
		//Subtracted value gives the relative delay between start of recording and
		//current message. We use this at playback to reproduce this delay.
		pMsg->time -= start_time;

		if (pMsg->time < 0)
			pMsg->time = 0;

		EVENTMSG msg = *pMsg;
		recorded_messages.push_back(msg);
	}

	bool AreMouseActionsIgnored () { return recording_options.ignore_mouse_actions; }

	RECORDINGOPTIONS GetRecordingOptions() { return recording_options; }
};